import time
from collections import OrderedDict
from datetime import datetime, timedelta
from types import FunctionType

from django.db.models import Sum, Count
from django.http import JsonResponse
from django.shortcuts import render, reverse
from django.utils.safestring import mark_safe

from web import models
from web.utils.pager import Pagernation


def get_attack_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        # date_time = obj.create_datetime
        # fatal_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
        #                                                        create_datetime__month=date_time.month,
        #                                                        create_datetime__day=date_time.day,
        #                                                        level=0).count()
        record_url = reverse('sangfor_fw_attacklog_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, obj.attack_count)
        return mark_safe(tpl)

    return inner


def get_fatal_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        fatal_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                               create_datetime__month=date_time.month,
                                                               create_datetime__day=date_time.day,
                                                               level=0).count()
        tpl = '<span>{:,}</span>'.format(fatal_count)
        return mark_safe(tpl)

    return inner


def get_high_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        high_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                              create_datetime__month=date_time.month,
                                                              create_datetime__day=date_time.day,
                                                              level=1).count()
        tpl = '<span>{:,}</span>'.format(high_count)
        return mark_safe(tpl)

    return inner


def get_middle_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        middle_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                                create_datetime__month=date_time.month,
                                                                create_datetime__day=date_time.day,
                                                                level=2).count()
        tpl = '<span>{:,}</span>'.format(middle_count)
        return mark_safe(tpl)

    return inner


def get_low_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        low_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                             create_datetime__month=date_time.month,
                                                             create_datetime__day=date_time.day,
                                                             level=3).count()
        tpl = '<span>{:,}</span>'.format(low_count)
        return mark_safe(tpl)

    return inner


def get_info_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        info_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                              create_datetime__month=date_time.month,
                                                              create_datetime__day=date_time.day,
                                                              level=4).count()
        tpl = '<span>{:,}</span>'.format(info_count)
        return mark_safe(tpl)

    return inner


def get_attackip_count(text, field):
    """
    获取choice字段的文本
    :param text: choice字段的名称
    :param field: choice字段
    :return:
    """

    def inner(obj=None, is_header=None, *args, **kwargs):
        if is_header:
            return text
        date_time = obj.create_datetime
        attackip_count = models.SangforFwAttackLog.objects.filter(create_datetime__year=date_time.year,
                                                                  create_datetime__month=date_time.month,
                                                                  create_datetime__day=date_time.day,
                                                                  ).values('src_ip').annotate(
            ct=Count('src_ip')).count()
        record_url = reverse('sangfor_attackip_list', kwargs={'pk': obj.id})
        tpl = '<a class="btn btn-info" href="{}">{:,}</a>'.format(record_url, attackip_count)
        return mark_safe(tpl)

    return inner


def sangfor_fw_list(request):
    list_display = [
        get_fatal_count('致命', 'attack_count'),
        get_high_count('高危', 'attack_count'),
        get_middle_count('中危', 'attack_count'),
        get_low_count('低危', 'attack_count'),
        get_info_count('信息', 'attack_count'),
        get_attack_count('攻击总数', 'attack_count'),
        get_attackip_count('攻击IP数', 'attack_count'),
        'update_datetime'
    ]
    queryset = models.SangforFw.objects.all().order_by('-update_datetime')
    model_class = models.SangforFw
    pager = Pagernation(request, queryset)
    # 1.处理表头
    header_list = []
    if list_display:
        for key_or_func in list_display:
            if isinstance(key_or_func, FunctionType):
                header_list.append(key_or_func(None, True))
            else:
                verbose_name = model_class._meta.get_field(key_or_func).verbose_name
                header_list.append(verbose_name)
    else:
        header_list.append(model_class._meta.model_name)
    # 2.处理表格内容
    data_list = queryset[pager.start:pager.end]
    body_list = []
    for row in data_list:
        tr_list = []
        if list_display:
            for key_or_func in list_display:
                if isinstance(key_or_func, FunctionType):
                    tr_list.append(key_or_func(row, False))
                else:
                    tr_list.append('' if getattr(row, key_or_func) == None else getattr(row, key_or_func))
        else:
            tr_list.append(row)
        body_list.append(tr_list)

    context = {
        'body_list': body_list,
        'header_list': header_list,
        'pager': pager,
    }
    return render(request, 'sangfor_fw_list.html', context)


def get_data_dict(field, value):
    today = datetime.now().date() + timedelta(days=1)
    date_dict = OrderedDict()
    for i in range(0, 30):
        date = today - timedelta(days=i)
        date_dict[date.strftime("%Y-%m-%d")] = [time.mktime(date.timetuple()) * 1000, 0]
    if field == 'attack_count':
        queryset = models.SangforFw.objects.filter(create_datetime__gt=today - timedelta(days=29)).extra(
            select={'ctime': "DATE_FORMAT(web_sangforfw.create_datetime,'%%Y-%%m-%%d')"}).values('ctime').annotate(
            ct=Sum(field))
    else:
        queryset = models.SangforFwAttackLog.objects.filter(create_datetime__gt=today - timedelta(days=29),
                                                            level=field).extra(
            select={'ctime': "DATE_FORMAT(web_sangforfwattacklog.create_datetime,'%%Y-%%m-%%d')"}).values(
            'ctime').annotate(
            ct=Count('level'))
    for item in queryset:
        date_dict[item['ctime']][1] = item['ct']
    return {'name': value, 'data': list(date_dict.values())}


def account_chart(request):
    level_tuple = models.SangforFwAttackLog.level_choices
    account_mapping = {'attack_count': '攻击总数', 'level': level_tuple}
    data_list = []
    for k, v in account_mapping.items():
        if isinstance(v, tuple):
            for item in v:
                data_list.append(get_data_dict(item[0], item[1]))
        else:
            data_list.append(get_data_dict(k, v))
    return JsonResponse({'status': True, 'data': data_list})
